﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NFramework.ObjectModel
{
    public class ThreadSafeDictionary<TKey, TValue> : IDictionary<TKey, TValue>
    {
        #region ThreadSafe Members

        private Dictionary<TKey, TValue> _internal = new Dictionary<TKey, TValue>();
        private object _lock = new object();

        private void SafeAdd(TKey key, TValue value)
        {
            lock (_lock) { _internal.Add(key, value); }
        }

        private bool SafeContainsKey(TKey key)
        {
            lock (_lock) { return _internal.ContainsKey(key); }
        }

        private ICollection<TKey> SafeKeys
        {
            get { lock (_lock) { return _internal.Keys; } }
        }

        private bool SafeRemove(TKey key)
        {
            lock (_lock) { return _internal.Remove(key); }
        }

        private bool SafeTryGetValue(TKey key, out TValue value)
        {
            lock (_lock) { return _internal.TryGetValue(key, out value); }
        }

        private ICollection<TValue> SafeValues
        {
            get { lock (_lock) { return _internal.Values; } }
        }

        private TValue SafeGetItem(TKey key)
        {
            lock (_lock) { return _internal[key]; }
        }

        private void SafeSetItem(TKey key, TValue value)
        {
            lock (_lock) { _internal[key] = value; }
        }

        private void SafeClear()
        {
            lock (_lock) { _internal.Clear(); }
        }

        private int SafeCount
        {
            get { lock (_lock) { return _internal.Count; } }
        }

        private IEnumerator<KeyValuePair<TKey, TValue>> SafeGetEnumerator()
        {
            lock (_lock) { return _internal.GetEnumerator(); }
        }

        #endregion

        #region IDictionary<TKey,TValue> Members

        public void Add(TKey key, TValue value)
        {
            SafeAdd(key, value);
        }

        public bool ContainsKey(TKey key)
        {
            return SafeContainsKey(key);
        }

        public ICollection<TKey> Keys
        {
            get { return SafeKeys; }
        }

        public bool Remove(TKey key)
        {
            return SafeRemove(key);
        }

        public bool TryGetValue(TKey key, out TValue value)
        {
            return SafeTryGetValue(key, out value);
        }

        public ICollection<TValue> Values
        {
            get { return SafeValues; }
        }

        public TValue this[TKey key]
        {
            get
            {
                return SafeGetItem(key);
            }
            set
            {
                SafeSetItem(key, value);
            }
        }

        #endregion

        #region ICollection<KeyValuePair<TKey,TValue>> Members

        public void Add(KeyValuePair<TKey, TValue> item)
        {
            SafeAdd(item.Key, item.Value);
        }

        public void Clear()
        {
            SafeClear();
        }

        public bool Contains(KeyValuePair<TKey, TValue> item)
        {
            return SafeContainsKey(item.Key);
        }

        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
        {
            throw new NotImplementedException();
        }

        public int Count
        {
            get { return SafeCount; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(KeyValuePair<TKey, TValue> item)
        {
            return SafeRemove(item.Key);
        }

        #endregion

        #region IEnumerable<KeyValuePair<TKey,TValue>> Members

        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            return SafeGetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return SafeGetEnumerator();
        }

        #endregion
    }
}
